#!/usr/bin/python
# -*- coding: utf-8 -*-

import json
import os
import odbc_p.DB
from util.opends import OpenDS
from ConfigParser import RawConfigParser
from util.logger import process_log
import traceback
import datetime
from binlog_increase import Increase
from util.tools import get_db_tb_key

conf_source = {
'aliyun_binlogs':'''
{
  "user_info": {
    "ds_name": "", 
    "ds_password": "", 
    "ds_domain": ""
  }, 
  "db": [
    {
      "db_database": "", 
      "db_port": "", 
      "db_name": "", 
      "db_host": "",
      "db_increase_type":"aliyun_binlogs",
      "db_binlog": {
          "instance": "", 
          "secret": "", 
          "id": ""
      }, 
      "db_password": "", 
      "db_type": "MYSQL", 
      "db_tables": [
        {
          "name": ""
        }
      ]
    }
  ]
}
''',
'local_binlogs' : '''
{
  "user_info": {
    "ds_name": "", 
    "ds_password": "", 
    "ds_domain": ""
    
  }, 
  "db": [
    {
      "db_database": "", 
      "db_port": "", 
      "db_name": "", 
      "db_host": "",
      "db_increase_type":"local_binlogs",
      "db_binlog": "", 
      "db_password": "", 
      "db_type": "MYSQL", 
      "db_tables": [
        {
          "name": ""
        }
      ]
    }
  ]
}
'''
}
db_increase_types = ["aliyun_binlogs", 'local_binlogs']

class Configuration:
    def __init__(self):
        self._config_file = "./conf/opends.conf"
        self._load()

    def _load(self):
        file_object = open(self._config_file)
        try:
            self.config = json.loads(file_object.read())
        finally:
            file_object.close()

    def dump(self, conf):
        with open(self._config_file, 'w') as conf_file:
            conf_file.write(json.dumps(conf, indent=2))

    def conf_check_time(self):
        self.check_time_file = 'conf/check_time.conf'
        self.check_time_json = {}
        if not os.path.exists(self.check_time_file):
            with open(self.check_time_file, 'w') as f:
                pass
            return self.check_time_json
        file_object = open(self.check_time_file)
        try:
            self.check_time_json = json.loads(file_object.read())
            return self.check_time_json
        except Exception as e:
            return self.check_time_json
        finally:
            file_object.close()

    def dump_check_time(self, json_s):
        with open(self.check_time_file, 'w') as conf_file:
            conf_file.write(json.dumps(json_s, indent=2))

    def conf_check(self, check_file_json):
        if not os.path.exists(self._config_file):
            return self.get_result(u'请在当前目录添加%s配置文件' % self._config_file)
        file_object = open(self._config_file)
        try:
            self.config = json.loads(file_object.read())
        except Exception as e:
            process_log().info("config:%s" % e)
            return self.get_result(u'配置文件格式错误，请检查%s' % traceback.format_exc())
        finally:
            file_object.close()
        user_info = self.config.get('user_info', None)
        if not user_info.get('token'):
            user_info_keys = ['username', 'domain', 'password']
            for k in user_info_keys:
                if k in user_info:
                    if not user_info[k]:
                        return self.get_result(u'%s配置项不能为空' % k)
                else:
                    return self.get_result(u'缺少%s配置项' % k)
            try:
                ds_token = OpenDS().ds_login(user_info['domain'],
                                             user_info['username'],
                                             user_info['password'])['access_token']
                user_info['ds_token'] = ds_token

            except Exception as e:
                raise e
            pass
        else:
            user_info['ds_token'] = user_info['token']
        db = self.config.get('db', None)
        self.config['aliyun_id'] = ''
        self.config['aliyun_secret'] = ''
        self.config['db_binlog_instance'] = ''
        self.config['aliyun_binlog_end_time'] = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ')
        self.config['local_binlog_end_time'] = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ')
        if db:
            try:
                db_info_keys = ['type', 'server', 'port', 'uid', 'ds_name',
                                'pwd', 'database', 'append_table', 'db_increase_type']

                for db_info in db:
                    if db_info['db_increase_type'] in ('origin', 'file'):
                        continue
                    db_info['database'] = db_info['database'].lower()
                    for k in db_info_keys:
                        if k in db_info:
                            if not db_info[k]:
                                return self.get_result(u'%s配置项不能为空' % k)
                        else:
                            return self.get_result(u'缺少%s配置项' % k)
                    try:
                        db_p = odbc_p.DB.loader(db_info)
                        ###
                        db_info['db'] = db_p
                        ###
                    except Exception as e:

                        return self.get_result(u'config:数据库连接错误%s' % traceback.format_exc())
                    db_tables = db_info['append_table']

                    for table in db_tables:
                        if 'name' not in table:
                            return self.get_result(u'tables name字段不能为none')
                        table['name'] = table['name'].lower()
                        if db_p.has_table(db_info['database'], table['name']):
                            db_table_key_name, db_table_key_position = db_p.get_key_position(db_info['database'],
                                                                                             table['name'])
                            table['db_table_key_name'] = db_table_key_name.lower()
                            table['db_table_key_position'] = db_table_key_position
                            table['db_table_exist'] = True
                            table['charset'] = db_info['db'].get_table_charset(db_info['database'],table['name'])
                        else:
                            table['db_table_exist'] = False
                            process_log().info(u'指定的表%s不存在,跳过' % table['name'])
                            continue
                        binlog_sync_type = False
                        if get_db_tb_key(db_info['database'], table['name']) in check_file_json \
                            and table['db_table_exist'] \
                                and db_info['db_increase_type'] in ['aliyun_binlogs', 'local_binlogs']:
                            binlog_sync_type = True

                        ds_table_info = self.get_ds_table_info(user_info['ds_token'], db_info['db'],
                                                               db_info['database'], table['name'], binlog_sync_type, u'%s' % db_info['ds_name'])
                        ###
                        table['ds_id'] = ds_table_info['ds_id']
                        table['ds_tb_id'] = ds_table_info['ds_tb_id']
                        table['ds_fields'] = OpenDS().field_list(user_info['ds_token'], ds_table_info['ds_tb_id'])
                        table['ds_table_exist'] = ds_table_info['ds_table_exist']
                        ###

                    if db_info['db_increase_type'] == 'aliyun_binlogs':
                        if not os.path.exists('binlogs'):
                            os.mkdir('binlogs')
                        db_binlog = db_info['db_binlog']
                        import platform
                        system_s = platform.system().lower()
                        if system_s == 'darwin':
                            db_binlog['mysqlbinlog'] = './tool_bin/mysqlbinlog_darwin'
                        elif system_s == 'windows':
                            db_binlog['mysqlbinlog'] = './tool_bin/mysqlbinlog_windows'
                        else:
                            db_binlog['mysqlbinlog'] = './tool_bin/mysqlbinlog_linux'
                        if not os.path.exists(db_binlog['mysqlbinlog']):
                            return self.get_result(u'指定的%s工具不存在' % db_binlog['mysqlbinlog'])
                        import aliyun.api
                        self.config['aliyun_id'] = db_info['db_binlog']['id']
                        self.config['aliyun_secret'] = db_info['db_binlog']['secret']
                        self.config['db_binlog_instance'] = db_info['db_binlog']['instance']
                        ###
                        for table in db_tables:
                            db_tb_time_key = get_db_tb_key(db_info['database'], table['name'])
                            if db_tb_time_key in check_file_json:
                                db_table_last_time = check_file_json[db_tb_time_key]
                                if self.config['aliyun_binlog_end_time'] > db_table_last_time:
                                    self.config['aliyun_binlog_end_time'] = db_table_last_time
                    elif db_info['db_increase_type'] == 'local_binlogs':
                        db_binlog = db_info['db_binlog']
                        if not os.path.exists(db_binlog['path']):
                            return self.get_result(u'指定的%s目录不存在' % db_binlog['path'])
                        import platform
                        system_s = platform.system().lower()
                        if system_s == 'darwin':
                            db_binlog['mysqlbinlog'] = './tool_bin/mysqlbinlog_darwin'
                        elif system_s == 'windows':
                            db_binlog['mysqlbinlog'] = '.\\tool_bin\\mysqlbinlog_windows.exe'
                        else:
                            db_binlog['mysqlbinlog'] = './tool_bin/mysqlbinlog_linux'
                        if not os.path.exists(db_binlog['mysqlbinlog']):
                            return self.get_result(u'指定的%s工具不存在' % db_binlog['mysqlbinlog'])
                        for table in db_tables:
                            db_tb_time_key = get_db_tb_key(db_info['database'], table['name'])
                            if db_tb_time_key in check_file_json:
                                db_table_last_time = check_file_json[db_tb_time_key]
                                if self.config['local_binlog_end_time'] > db_table_last_time:
                                    self.config['local_binlog_end_time'] = db_table_last_time
                    elif db_info['db_increase_type'] == 'force_full':
                        pass
                    elif db_info['db_increase_type'] == 'md5_diff':
                        pass
                    else:
                        return self.get_result(u'指定的db_increase_type="%s"无效' % db_info['db_increase_type'])
            except Exception as e:
                return self.get_result(u'config:解析db配置错误%s\n' % traceback.format_exc())
        else:
            return self.get_result(u'缺少db_info配置项')
        if self.config['aliyun_id']:
            aliyun.setDefaultAppInfo(self.config['aliyun_id'], self.config['aliyun_secret'].encode("utf-8"))
            a = aliyun.api.Rds20140815DescribeBinlogFilesRequest()
            a.DBInstanceId = self.config['db_binlog_instance']
            s_t = self.config['aliyun_binlog_end_time']
            s_t = datetime.datetime.strptime(s_t, '%Y-%m-%dT%H:%M:%SZ')+datetime.timedelta(hours=-18)
            s_t = s_t.strftime('%Y-%m-%dT%H:%M:%SZ')
            a.StartTime = s_t
            a.EndTime = datetime.datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ')
            try:
                f = a.getResponse()
                if 'Message' in f:
                    return self.get_result(f['Message'])
                binlog_files = f["Items"]["BinLogFile"][::-1]
                ###
                self.config['db_binlog_files'] = binlog_files
                ###
                process_log().info("binlog_files:%s" % binlog_files)
            except Exception, e:
                return self.get_result('aliyun get_response:%s' % traceback.format_exc())
        return {'status': 1}

    def get_result(self, info):
        res = {'status': 0, 'result': info}
        process_log().error("config:%s" % info)
        return res

    def get_ds_table_info(self, token, db_p, database, table, binlog_sync_type, ds_name):
        table_info = {'ds_id': None, 'ds_tb_id': None, 'ds_table_exist': False}
        try:
            exist_ds_list = OpenDS().ds_list(token)
        except Exception, e:
            process_log().error(e.message)
        for db in exist_ds_list['data_source']:
            if db['name'] == ds_name:
                table_info['ds_id'] = db['ds_id']
                for tb in db['tables']:
                    if table == tb[0]:
                        Increase().init_schema(token, db_p, database, table_info['ds_id'], table, tb[1], binlog_sync_type)
                        table_info['ds_tb_id'] = tb[1]
                        table_info['ds_table_exist'] = True
                        return table_info
        if not table_info['ds_id']:
            ds_id = OpenDS().ds_create(token, ds_name)['ds_id']
            table_info['ds_id'] = ds_id
        ds_tb_id = Increase().init_schema(token, db_p, database, table_info['ds_id'], table, None, binlog_sync_type)[
            'ds_tb_id']
        table_info['ds_tb_id'] = ds_tb_id
        return table_info


def get(sect, opt):
    configger = RawConfigParser()
    configger.read('./conf/logging.conf')
    return configger.get(sect, opt)
